package edu.utexas.ipc;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.StringTokenizer;

public class ConnectProcessHandler implements ConnectHandler {

	final int SOCKET_TIMEOUT = 5000;
	
	Linker linker;
	MessageListener msgOut;
	Clock clock;
	
	ConnectProcessHandler(Clock clock, Linker linker, MessageListener msgOut) {
		this.linker = linker;
		this.msgOut = msgOut;
		this.clock = clock;
	}
	
	/**
	 * Handle incoming connections from the Connector.
	 */
	public void processConnection(Socket sckt) {
		try {
			
			// sckt.setSoTimeout(SOCKET_TIMEOUT);
			
			BufferedWriter scktOut = new BufferedWriter(new OutputStreamWriter(sckt.getOutputStream()));
			BufferedReader scktIn = new BufferedReader(new InputStreamReader(sckt.getInputStream()));
			
			// send a hello message
			scktOut.write(linker.getProcessID() + " -1 " + "hello " + clock.value() + " #\n");
			scktOut.flush();
			clock.tick();
			
			// receive hello message from process
			String helloMessage = scktIn.readLine();
			// System.out.println("-- " + helloMessage);
			StringTokenizer st = new StringTokenizer(helloMessage);
	        int peerID = Integer.parseInt(st.nextToken());
	        int nullID = Integer.parseInt(st.nextToken());
	        String tag = st.nextToken();
	        String timestamp = st.nextToken();
	        if (nullID == -1 && tag.equals("hello")) {
	        	
	        	// synchronize clocks
	        	clock.update(peerID, timestamp);
	        	
	        	// got valid response from the server.  Save the socket and streams
	        	linker.setupLink(peerID, sckt, scktIn, scktOut);
	        	
	        	MessageSource msgIn = new LinkerMessageSource(peerID, linker);
	        	
	        	// start the receive thread for this connection
	        	new ReceiveThread(peerID, msgIn, msgOut).start();
	        	return;
	        }
	        
		} catch (IOException e) {
			e.printStackTrace();
			
			try {
				sckt.close();
			} catch (IOException ce) {
				ce.printStackTrace();
			}
		}
	}
}
